package com.micaelvesterlund.skeerkie.shared.domain;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.micaelvesterlund.skeerkie.shared.util.LineUpGenerator;

public class League {
	private List<Team> teams;
	private List<Game> games;
	private List<Round> rounds;

	public List<Game> getGames() {
		return games;
	}

	public League(List<Team> teams) {
		this.teams = teams;

		int nrOfRounds = (teams.size() - 1) * 2;
		int nrOfGames = (teams.size() / 2);
		rounds = new ArrayList<Round>(nrOfRounds);
		for (int i = 0; i < nrOfRounds; i++) {
			Round round = new Round(nrOfGames);
			rounds.add(round);
		}

		createGamesInRounds();
		Collections.shuffle(rounds);
	}

	private void createGamesInRounds() {
		List<Team> tempList = new ArrayList<Team>();
		for (Team team : teams) {
			tempList.add(team);
		}
		List<Game> gameList = new ArrayList<Game>();
		while (tempList.size() > 0) {
			gameList.addAll(createGames(tempList));
			tempList.remove(0);
		}
		games = gameList;
	}

	private List<Game> createGames(List<Team> teamList) {
		List<Game> gameList = new ArrayList<Game>();
		Team[] array = (Team[]) teamList.toArray(new Team[teamList.size()]);
		Team team0 = array[0];
		LineUpGenerator lineUpGenerator = new LineUpGenerator();
		for (int i = 1; i < array.length; i++) {
			Team team1 = array[i];
			Game game = new Game(lineUpGenerator.create(team0),
					lineUpGenerator.create(team1));
			gameList.add(game);
			addGameToRound(team0, game);
		}
		for (int i = 1; i < array.length; i++) {
			Team team1 = array[i];
			Game game = new Game(lineUpGenerator.create(team1),
					lineUpGenerator.create(team0));
			gameList.add(game);
			addGameToRound(team0, game);
		}
		return gameList;
	}

	private void addGameToRound(Team team, Game gameToAdd) {
		for (Round round : rounds) {
			Game[] gamesInRound = round.getGames();
			boolean foundTeam = false;
			boolean gameAdded = false;
			Team home = gameToAdd.getHomeLineUp().getTeam();
			Team away = gameToAdd.getAwayLineUp().getTeam();
			for (int j = 0; j < gamesInRound.length; j++) {
				Game gameInRound = gamesInRound[j];
				if (gameInRound != null) {
					if (teamInGame(home, gameInRound)
							|| teamInGame(away, gameInRound)) {
						// team already in this round try next one
						foundTeam = true;
						break;
					}
				}
			}
			if (!foundTeam) {
				for (int j = 0; j < gamesInRound.length; j++) {
					Game game = gamesInRound[j];
					if (game == null) {
						gamesInRound[j] = gameToAdd;
						gameAdded = true;
						break;
					}
				}
			}
			if (gameAdded) {
				break;
			}
		}
	}

	private boolean teamInGame(Team team, Game gameInRound) {
		return (gameInRound.getHomeLineUp().getTeam().equals(team))
				|| (gameInRound.getAwayLineUp().getTeam().equals(team));
	}

	public List<Team> getTeams() {
		return teams;
	}

	public List<Round> getRounds() {
		return rounds;
	}

	@Override
	public String toString() {
		return "League [teams=" + teams + ", games=" + games + "]";
	}

}
